package com.duoduo.common.api.help;

import com.duoduo.common.api.constants.Constant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

public class DateInnerUtil {
	
	private static final Logger logger = LoggerFactory.getLogger(DateInnerUtil.class);
	private static final int MAX_MONTH = 12; // 每年最大月数
	private static final int FIRST_DAY = 1; // 每月第一天

	/**按指定格式返回当前时间字符串
	 * @param format
	 * @return
	 */
	public static String getNowString(String format){
		return getStringDay(new Date(), format);
	}
	/**获取当前时间的long
	 *
	 * @return
	 */
	public static long getTodayLong() {
		Date date = new Date();
		return date.getTime();
	}

	/**获取当前时间的long
	 *
	 * @return
	 */
	public static long getTodayLong(String type) {
		Date date = new Date();
		SimpleDateFormat matter = new SimpleDateFormat(Constant.DEFAULT_SHORT_DATE_FORMAT);
		matter.format(date);
		return date.getTime();
	}

	/**按YYYY-MM-DD HH:MM:SS格式返回今天的日期.
	 *
	 * @return String
	 */
	public static String getToday() {
		return getStringDay(new Date(), Constant.DEFAULT_DATE_FORMAT);
	}

	/**按YYYY-MM-DD格式返回今天的日期.
	 *
	 * @return String
	 */
	public static String getToday2() {
		return getStringDay(new Date(), Constant.DEFAULT_SHORT_DATE_FORMAT);
	}

	/**将字符串日期转换为type格式的日期类型
     * @param dateTimeStr
     * @param type 日期格式
     * @return
     * 2014年11月10日
     */
    public static Date getDateByStringOnType(String dateTimeStr, String type) {
    	Date date = null;
    	SimpleDateFormat ft = new SimpleDateFormat(type);
    	try {
			date = ft.parse(dateTimeStr);
		} catch (ParseException e) {
			logger.error(Constant.EMPTY_STRING, e);
		}
        return date;
    }

    /**将字符串日期转换为type格式的日期类型
     * @param dateTimeStr
     * @return
     * 2014年11月10日
     */
    public static Date getDateByStringOnType(String dateTimeStr) {
    	Date date = null;
    	SimpleDateFormat ft = new SimpleDateFormat(Constant.DEFAULT_DATE_FORMAT);
    	try {
    		date = ft.parse(dateTimeStr);
    	} catch (ParseException e) {
    		logger.error(Constant.EMPTY_STRING, e);
    	}
    	return date;
    }

	/**Date转String
	 *
	 * @return String
	 */
	public static String getStringDay(Date date) {
		SimpleDateFormat formatter = new SimpleDateFormat(Constant.DEFAULT_DATE_FORMAT); // 规定日期格式
		return formatter.format(date); // 将Date转换为符合格式的String
	}
	
	/**long转String
	 *
	 * @return String
	 */
	public static String getStringDay(long mills) {
		SimpleDateFormat formatter = new SimpleDateFormat(Constant.DEFAULT_DATE_FORMAT); // 规定日期格式
		return formatter.format(new Date(mills)); // 将Date转换为符合格式的String
	}

	/**按指定格式返回日期.
	 *
	 * @return String
	 */
	public static String getStringDay(Date date, String format) {
		SimpleDateFormat formatter = new SimpleDateFormat(format); // 规定日期格式
		return formatter.format(date); // 将Date转换为符合格式的String
	}

	/**按指定格式返回日期.
	 *
	 * @return Date
	 */
	public static Date getDateDay(String date, String format) {
		SimpleDateFormat formatter = new SimpleDateFormat(format); // 规定日期格式
		try {
			return formatter.parse(date);
		} catch (ParseException e) {
			logger.error(Constant.EMPTY_STRING, e);
			return null;
		}
	}
	
	/**按指定格式返回日期.
	 *
	 * @return Date
	 */
	public static Date getDateDay(Date date, String format) {
		String str = getStringDay(date, format);
		return getDateDay(str, format);
	}

	/**按指定格式返回日期.
	 *
	 * @return Date
	 */
	public static Date getDateDay(Long date) {
		return new Date(date);
	}

	/**根据秒数，格式化输出时间（mm:ss/HH:mm:ss）
     *
     * @param seconds
     * @return
     */
	public static String msSecondsToTime(long msSeconds) {
		String showTime = "";
		long hour = (msSeconds % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60);
		if (hour < 10) {
            showTime += "0" + hour + ":";
        } else {
            showTime += hour + ":";
        }
	    long minute = (msSeconds % (1000 * 60 * 60)) / (1000 * 60);
	    if (minute < 10) {
            showTime += "0" + minute + ":";
        } else {
            showTime += minute + ":";
        }
	    long second = (msSeconds % (1000 * 60)) / 1000;
	    if (second < 10) {
	    	showTime += "0" + second;
	    } else {
	    	showTime += second;
	    }
	    return showTime + ":" + msSeconds % 1000;

	}

	/**根据秒数，格式化输出时间（mm:ss/HH:mm:ss）
     *
     * @param seconds
     * @return
     */
    public static String secondsToTime(int seconds) {
        String showTime = "";
        int second = seconds % 60;
        int minute = seconds / 60;
        int hour = 0;
        if (minute >= 60) {
            hour = minute / 60;
            minute = minute % 60;
        }
        if (hour != 0) {
            if (hour < 10) {
                showTime += "0" + hour + ":";
            } else {
                showTime += hour + ":";
            }
        }
        if (minute < 10) {
            showTime += "0" + minute + ":";
        } else {
            showTime += minute + ":";
        }
        if (second < 10) {
            showTime += "0" + second;
        } else {
            showTime += second;
        }

        return showTime;
    }

    /**增加\减少seconds秒后的日期
     *
     * @param endDate
     * @return
     */
    public static Date getAddSecondDay(Date date, int seconds) {
        if (date == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.SECOND, seconds);
        return calendar.getTime();
    }

	/**计算给定的两个时间相差的秒数:end - start
	 * @param start
	 * @param end
	 * @return
	 */
	public static long getDiffNum(String start, String end) {
		long quot = 0;
		SimpleDateFormat ft = new SimpleDateFormat(Constant.DEFAULT_DATE_FORMAT);
		try {
			Date d_start = ft.parse(start);
			Date d_end = ft.parse(end);
			return getDiffNum(d_start, d_end);
		} catch (ParseException e) {
			logger.error(Constant.EMPTY_STRING, e);
		}
		return quot;
	}

	/**计算给定的两个时间相差的秒数:end - start
	 * @param start
	 * @param end
	 * @return
	 */
	public static long getDiffNum(Date start, Date end) {
		long quot = 0;
		quot = end.getTime() - start.getTime();
		quot = quot / 1000;
		return Math.abs(quot);
	}

	/**通过String类型的日期字符串对日期进行加减运算
	 * @param date
	 * @param type
	 * @param num
	 * @return
	 * @throws ParseException
	 */
	public static String getDateSub(String date, String type, int num) throws ParseException{
		SimpleDateFormat ft = new SimpleDateFormat(Constant.DEFAULT_DATE_FORMAT);
		Date d = ft.parse(date);
		Date dSub = getDateSub(d, type, num);
		return ft.format(dSub);
	}
	/**对日期时间进行加减运算操作
	 * @param date
	 * @param type
	 *            y = year m = month d = date h = hour m = minute s = second
	 * @param num
	 *            正数加法 负数减法
	 * @return
	 */
	public static Date getDateSub(Date date, String type, int num) {
		Calendar calender = Calendar.getInstance();
		calender.setTime(date);
		if (type.equals("y")) {
			calender.add(Calendar.YEAR, num);
		}
		if (type.equals("M")) {
			calender.add(Calendar.MONTH, num);
		}
		if (type.equals("d")) {
			calender.add(Calendar.DATE, num);
		}
		if (type.equals("h")) {
			calender.add(Calendar.HOUR, num);
		}
		if (type.equals("m")) {
			calender.add(Calendar.MINUTE, num);
		}
		if (type.equals("s")) {
			calender.add(Calendar.SECOND, num);
		}
		return calender.getTime();
	}

	/**对日期时间进行加减运算操作
	 * @param date
	 * @param type
	 *            y = year m = month d = date h = hour m = minute s = second
	 * @param num
	 *            正数加法 负数减法
	 * @param resultFormat
	 *            结果日期的格式
	 * @return
	 */
	public static String getDateSub(String date, String type, int num, String resultFormat) {
		Date day = getDateByStringOnType(date);
		return getStringDay(getDateSub(day, type, num), resultFormat);
	}

	/**比较两个日期的大小
	 * @param date1
	 * @param date2
	 * @return 0 相等 + 大于 - 小于
	 */
	public static int compareDate(String date1, String date2) {
		SimpleDateFormat ft = new SimpleDateFormat(Constant.DEFAULT_DATE_FORMAT);
		Calendar c1 = Calendar.getInstance();
		Calendar c2 = Calendar.getInstance();
		try {
			c1.setTime(ft.parse(date1));
			c2.setTime(ft.parse(date2));
		} catch (Exception e) {
			logger.error(Constant.EMPTY_STRING, e);
		}
		return c1.compareTo(c2);
	}

	/**返回指定的日期格式
	 *
	 * @param type
	 * @return
	 */
	public static String getDayFormat(String dateStr, String type) {
		SimpleDateFormat formatter = new SimpleDateFormat(type); // 规定日期格式
		Date date = getDateByString(dateStr); // 将符合格式的String转换为Date
		String today = formatter.format(date); // 将Date转换为符合格式的String
		return today;
	}

	public static Date getDateByString(String dateTimeStr) {
		Date date = null;
		SimpleDateFormat ft = null;
		if(dateTimeStr.indexOf(" ") > -1){
			ft = new SimpleDateFormat(Constant.DEFAULT_DATE_FORMAT);
		}else{
			ft = new SimpleDateFormat(Constant.DEFAULT_SHORT_DATE_FORMAT);
		}
		try {
			date = ft.parse(dateTimeStr);
		} catch (ParseException e) {
			logger.error(Constant.EMPTY_STRING, e);
		}

		return date;

	}

	/**获取月份的天数
     * @param year
     * @param month
     * @return
     */
    public static int getDaysOfMonth(int year, int month) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month - 1, 1);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    /**获取日期的年
     * @param date
     * @return
     */
    public static int getYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.YEAR);
    }

    /**获取日期的月
     * @param date
     * @return
     */
    public static int getMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MONTH) + 1;
    }

    /**获取日期的日
     * @param date
     * @return
     */
    public static int getDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.DATE);
    }

    /**获取日期的时
     * @param date
     * @return
     */
    public static int getHour(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.HOUR);
    }

    /**获取日期的分种
     * @param date
     * @return
     */
    public static int getMinute(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MINUTE);
    }

    /**获取日期的秒
     * @param date
     * @return
     */
    public static int getSecond(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.SECOND);
    }

    /**获取星期几
     * @param date
     * @return
     */
    public static int getWeekDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        return dayOfWeek-1;
    }

    /**获取哪一年共有多少周
     * @param year
     * @return
     */
    public static int getMaxWeekNumOfYear(int year) {
        Calendar c = new GregorianCalendar();
        c.set(year, Calendar.DECEMBER, 31, 23, 59, 59);
        return getWeekNumOfYear(c.getTime());
    }

    /**取得某天是一年中的多少周
     * @param date
     * @return
     */
    public static int getWeekNumOfYear(Date date) {
        Calendar c = new GregorianCalendar();
        c.setFirstDayOfWeek(Calendar.MONDAY);
        c.setMinimalDaysInFirstWeek(7);
        c.setTime(date);
        return c.get(Calendar.WEEK_OF_YEAR);
    }

    /**取得某天所在周的第一天
     * @param year
     * @return
     */
    public static Date getFirstDayOfWeek(Date date) {
        Calendar c = new GregorianCalendar();
        c.setFirstDayOfWeek(Calendar.MONDAY);
        c.setTime(date);
        c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek());
        return c.getTime();
    }

    /**取得某天所在周的最后一天
     * @param date
     * @return
     */
    public static Date getLastDayOfWeek(Date date) {
        Calendar c = new GregorianCalendar();
        c.setFirstDayOfWeek(Calendar.MONDAY);
        c.setTime(date);
        c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek() + 6);
        return c.getTime();
    }

    /**取得某年某周的第一天 对于交叉:2008-12-29到2009-01-04属于2008年的最后一周,2009-01-05为2009年第一周的第一天
     * @param year
     * @param week
     * @return
     */
    public static Date getFirstDayOfWeek(int year, int week) {
        Calendar calFirst = Calendar.getInstance();
        calFirst.set(year, 0, 7);
        Date firstDate = getFirstDayOfWeek(calFirst.getTime());

        Calendar firstDateCal = Calendar.getInstance();
        firstDateCal.setTime(firstDate);

        Calendar c = new GregorianCalendar();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, Calendar.JANUARY);
        c.set(Calendar.DATE, firstDateCal.get(Calendar.DATE));

        Calendar cal = (GregorianCalendar) c.clone();
        cal.add(Calendar.DATE, (week - 1) * 7);
        firstDate = getFirstDayOfWeek(cal.getTime());

        return firstDate;
    }

    /**取得某年某周的最后一天 对于交叉:2008-12-29到2009-01-04属于2008年的最后一周, 2009-01-04为
     * 2008年最后一周的最后一天
     * @param year
     * @param week
     * @return
     */
    public static Date getLastDayOfWeek(int year, int week) {
        Calendar calLast = Calendar.getInstance();
        calLast.set(year, 0, 7);
        Date firstDate = getLastDayOfWeek(calLast.getTime());

        Calendar firstDateCal = Calendar.getInstance();
        firstDateCal.setTime(firstDate);

        Calendar c = new GregorianCalendar();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, Calendar.JANUARY);
        c.set(Calendar.DATE, firstDateCal.get(Calendar.DATE));

        Calendar cal = (GregorianCalendar) c.clone();
        cal.add(Calendar.DATE, (week - 1) * 7);
        Date lastDate = getLastDayOfWeek(cal.getTime());

        return lastDate;
    }

    private static Date add(Date date, int calendarField, int amount) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        } else {
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.add(calendarField, amount);
            return c.getTime();
        }
    }

    /*
     * 1则代表的是对年份操作， 2是对月份操作， 3是对星期操作， 5是对日期操作， 11是对小时操作， 12是对分钟操作， 13是对秒操作，
     * 14是对毫秒操作
     */

    /**增加年
     * @param date
     * @param amount
     * @return
     */
    public static Date addYears(Date date, int amount) {
        return add(date, 1, amount);
    }

    /**增加月
     * @param date
     * @param amount
     * @return
     */
    public static Date addMonths(Date date, int amount) {
        return add(date, 2, amount);
    }

    /**增加周
     * @param date
     * @param amount
     * @return
     */
    public static Date addWeeks(Date date, int amount) {
        return add(date, 3, amount);
    }

    /**增加天
     * @param date
     * @param amount
     * @return
     */
    public static Date addDays(Date date, int amount) {
        return add(date, 5, amount);
    }

    /**增加时
     * @param date
     * @param amount
     * @return
     */
    public static Date addHours(Date date, int amount) {
        return add(date, 11, amount);
    }

    /**增加分
     * @param date
     * @param amount
     * @return
     */
    public static Date addMinutes(Date date, int amount) {
        return add(date, 12, amount);
    }

    /**增加秒
     * @param date
     * @param amount
     * @return
     */
    public static Date addSeconds(Date date, int amount) {
        return add(date, 13, amount);
    }

    /**增加毫秒
     * @param date
     * @param amount
     * @return
     */
    public static Date addMilliseconds(Date date, int amount) {
        return add(date, 14, amount);
    }
    
    private static Date set(Date date, int calendarField, int amount) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        } else {
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.set(calendarField, amount);
            return c.getTime();
        }
    }
    
    /**设置年
     * @param date
     * @param year
     * @return
     */
    public static Date setYears(Date date, int year) {
    	int month = getMonth(date);
    	Date tmp = set(date, 1, year);
    	// 做日期校验
    	int newMonth = getMonth(tmp);
    	if(newMonth > month) {
    		tmp = setDays(tmp, FIRST_DAY);
    		tmp = addDays(tmp, -1);
    	}
    	return tmp;
    }

    /**设置月，如果传入的天数大于指定月份的最后一天，则直接取最后一天
     * @param date
     * @param month
     * @return
     */
    public static Date setMonths(Date date, int month) {
    	if(month > MAX_MONTH) {
    		throw new IllegalArgumentException("month must less or equals " + MAX_MONTH);
    	}
    	Date tmp = set(date, 2, month - 1);
    	// 做日期校验
    	int newMonth = getMonth(tmp);
    	if(newMonth > month) {
    		tmp = setDays(tmp, FIRST_DAY);
    		tmp = addDays(tmp, -1);
    	}
    	return tmp;
    }
    
    /**设置天
     * @param date
     * @param amount
     * @return
     */
    public static Date setDays(Date date, int day) {
    	int month = getMonth(date);
    	Date tmp = set(date, 5, day);
    	// 做日期校验
    	int newMonth = getMonth(tmp);
    	if(newMonth > month) {
    		tmp = setDays(tmp, FIRST_DAY);
    		tmp = addDays(tmp, -1);
    	}
    	return tmp;
    }

	/**time差
     * @param before
     * @param after
     * @return
     */
    public static long diffTimes(Date before, Date after){
    	return after.getTime() - before.getTime();
    }

	/**秒差
	 * 
	 * @param before
	 * @param after
	 * @return
	 */
	public static long diffSecond(Date before, Date after) {
		return (after.getTime() - before.getTime()) / 1000;
	}

	/**分种差
	 * 
	 * @param before
	 * @param after
	 * @return
	 */
	public static int diffMinute(Date before, Date after) {
		return (int) (after.getTime() - before.getTime()) / 1000 / 60;
	}

	/**时差
	 * 
	 * @param before
	 * @param after
	 * @return
	 */
	public static int diffHour(Date before, Date after) {
		return (int) (after.getTime() - before.getTime()) / 1000 / 60 / 60;
	}
	
	/**天数差，按毫秒数计算天数差
	 * 
	 * @param before
	 * @param after
	 * @return
	 */
	public static int diffDay(Date before, Date after) {
		return Integer.parseInt(String.valueOf(((after.getTime() - before.getTime()) / 86400000)));
	}

	/**天数差，按天数计算天数差
	 * 
	 * @param before
	 * @param after
	 * @return
	 */
	public static int diffDayByDay(Date before, Date after) {
		Calendar calBefore = Calendar.getInstance();
        calBefore.setTime(before);
        
        Calendar calAfter = Calendar.getInstance();
        calAfter.setTime(after);
        int dayBefore = calBefore.get(Calendar.DAY_OF_YEAR);
        int dayAfter = calAfter.get(Calendar.DAY_OF_YEAR);
        
        int yearBefore = calBefore.get(Calendar.YEAR);
        int yearAfter = calAfter.get(Calendar.YEAR);
        if(yearBefore != yearAfter) {   // 不同一年
            int timeDistance = 0 ;
            for(int i = yearBefore; i < yearAfter; i ++) {
                if(i%4 == 0 && i%100 != 0 || i%400 == 0) {    // 闰年            
                    timeDistance += 366;
                }else {   // 不是闰年
                    timeDistance += 365;
                }
            }
            
            return timeDistance + (dayAfter - dayBefore);
        }else {    // 同一年
            return dayAfter - dayBefore;
        }
	}

	/**月差
	 * 
	 * @param before
	 * @param after
	 * @return
	 */
	public static int diffMonth(Date before, Date after) {
		int monthAll = 0;
		int yearsX = diffYear(before, after);
		Calendar c1 = Calendar.getInstance();
		Calendar c2 = Calendar.getInstance();
		c1.setTime(before);
		c2.setTime(after);
		int monthsX = c2.get(Calendar.MONTH) - c1.get(Calendar.MONTH);
		monthAll = yearsX * 12 + monthsX;
		int daysX = c2.get(Calendar.DATE) - c1.get(Calendar.DATE);
		if (daysX > 0) {
			monthAll = monthAll + 1;
		}
		return monthAll;
	}

	/**年差
	 * 
	 * @param before
	 * @param after
	 * @return
	 */
	public static int diffYear(Date before, Date after) {
		return getYear(after) - getYear(before);
	}

	/**设置23:59:59
	 * 
	 * @param date
	 * @return
	 */
	public static Date setEndDay(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR_OF_DAY, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		return calendar.getTime();
	}

	/**设置00:00:00
	 * 
	 * @param date
	 * @return
	 */
	public static Date setStartDay(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR_OF_DAY, 00);
		calendar.set(Calendar.MINUTE, 00);
		calendar.set(Calendar.SECOND, 00);
		return calendar.getTime();
	}

	/**获取指定日期所在月份第一天的日期
	 * 
	 * @param date
	 * @return 格式化后的日期
	 */
	public static Date getFirstDayOfMonth(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.DAY_OF_MONTH, 1);
		return setStartDay(cal.getTime());
	}

	/**获取指定日期所在月份的下个月的第一天的日期
	 * 
	 * @param date
	 * @return 格式化后的日期
	 */
	public static Date getFirstDayOfNextMonth(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.DAY_OF_MONTH, 1);
		cal.add(Calendar.MONTH, 1);
		return setStartDay(cal.getTime());
	}

	/**获取指定日期所在月份最后一天的日期
	 * 
	 * @return 格式化的日期
	 */
	public static Date getLastDayOfMonth(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.DATE, 1);
		// 主要就是这个roll方法
		cal.roll(Calendar.DATE, -1);
		return setStartDay(cal.getTime());
	}
	
	/**输入的日期是否是指定的day，比如date=2021-09-08, day=8，返回true
	 * @param date
	 * @param day
	 * @return
	 */
	public static boolean isDay(Date date, int day) {
		int day1 = getDay(date);
		if(day1 == day) {
			return true;
		}
		return false;
	}

}
